﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Configuration;
using System.IO;
using Facebook.Utils;
using Facebook.Channels;
using Facebook.Services;
using Social.Core;
using Social.Core.Protocols;


namespace Facebook.Web
{
    /// <summary>
    /// IHttpModule Implementation to make OAuth Authentication 
    /// </summary>
    public class FbAuthenticationModule : IHttpModule
    { 
         Facebookconfig  fbconfig = null;
         FacebookChannel fbchannel = null;
         FacebookService fbservice = null;
         OAuth2_0 protocol = null;

         AuthRequestArgs authUtils = new AuthRequestArgs();

        public void Init(HttpApplication context)
        {
            
           context.BeginRequest += new EventHandler(context_BeginRequest);
           context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
        }


        void context_AuthorizeRequest(object sender, EventArgs e)
        {
            HttpApplication context = sender as HttpApplication;

        }

        void context_AcquireRequestState(object sender, EventArgs e)
        {

            HttpApplication context = sender as HttpApplication;
            try
            {
                if (context.Session != null)
                {
                    if (context.Session["facebookservice"] == null) 
                    {
                        if (context.Request.Params["access_token"] == null && context.Request.Path.Contains(".aspx"))
                        {
                            if (context.Request.Params["code"] == null)
                                AuthorizationRequest(context);
                            else
                            {
                               bool authResult =  AuthenticationFlow(context);
                                if(authResult )
                                    context.Session.Add("facebookservice", fbservice);
                            }
                            
                        }

                        
                    }
                        
                }
            }
            catch { }

        }

        
        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication context = sender as HttpApplication;
            
            string applicationPath = context.Request.ApplicationPath;

            authUtils.Config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(applicationPath);

             fbconfig = new Facebookconfig() 
             { 
                 ActionUrl = authUtils.GraphpUrl, 
                 ApiKey = authUtils.APIKey, 
                 ApplicationID = authUtils.ApplicationID, 
                 AppSecret = authUtils.AppSecret,  
                 FqlUrl = authUtils.FqlUrl, 
                 RequestFormatter = new RequestFormatter(),
                 Deserializer = new JsDeserializer(),
            };

             protocol = new OAuth2_0() 
             {
                Context = context,
                RequestFormat = fbconfig.RequestFormatter,
                AuthorizationRequestUrl = authUtils.ApplicationOAuthUrl,
                ClientCredentialsUrlRequest = authUtils.GraphpUrl
             };

             fbchannel = new FacebookChannel(fbconfig) 
             {
                Protocol = protocol
             };
             
                
             fbservice = new FacebookService(fbconfig, fbchannel);

        }


        #region private methods
        private void AuthorizationRequest(HttpApplication context)
        { 
            AuthorizationRequestArgs authArgs = new AuthorizationRequestArgs();
            authArgs.Add("client_id", authUtils.ApplicationID);
            authArgs.Add("redirect_uri", authUtils.ApplicationUri);
            authArgs.Add("scope", authUtils.UserPermissions);
             
            protocol.AuthorizationRequest("dialog/oauth", authArgs);

            //context.Response.Redirect(authUtils.AuthRequestUrl);
        }

        private bool AuthenticationFlow(HttpApplication context)
        {

            string aplicationUri = context.Request.Url.AbsoluteUri;
            // the user presses Don't Allow
            if (!String.IsNullOrWhiteSpace(context.Request.Params["error_reason"]))
            {
                string error = context.Request.Params["error"];
                string error_reason = context.Request.Params["error_reason"];
                string error_description = context.Request.Params["error_description"];

                context.Server.Transfer(String.Format("http://localhost/FbApp1/AccessDenied.aspx?error={0}&error_reason={1}&error_description={2}", error, error_reason, error_description));
                return false;
            }
            

            GetAccessToken(aplicationUri,  context);

            return true;

        }

        private void GetAccessToken(string aplicationUri,  HttpApplication context)
        {

            if (string.IsNullOrWhiteSpace(context.Request.Params["code"]))
                throw new Exception("Facebook authentication throw an error! code not available");

            aplicationUri = context.Request.Url.AbsoluteUri.Remove(context.Request.Url.AbsoluteUri.IndexOf('?'));

            string code = context.Request.Params["code"];

            ClientCredentials args = new ClientCredentials();
            args.Add("client_id", authUtils.ApplicationID);
            args.Add("redirect_uri", aplicationUri);
            args.Add("client_secret", authUtils.AppSecret);
            args.Add("code", code);

            //string access_token = fbchannel.RequestGraph("oauth/access_token", args);
            string access_token = protocol.ClientCredentialsRequest("oauth/access_token", args);

            fbconfig.AccessToken = access_token.Split('=')[1];

        }


        #endregion 

        public void Dispose()
        {
            
        }
    }
}